package editor.tester;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;

import org.jwalk.Modality;
import org.jwalk.Settings;
import org.jwalk.SettingsException;
import org.jwalk.Strategy;

import editor.Context;

/**
 * TestSettingsPanel is a kind of panel for selecting the test settings.
 * TestSettingsPanel is the upper-middle part of the InputPanel used in the 
 * JWalk Tester application.  It allows the user to supply the regular test
 * settings needed by the JWalker test engine.  The panel consists of a
 * combo-box to select the test Strategy (the default is ALGEBRA); a combo-box
 * to select the test Modality (the default is EXPLORE); and a spinner to 
 * select the maximum path depth for test sequences (the default is 3).  When 
 * the settings of this panel are committed, the test strategy, test modality
 * and test depth are uploaded to the JWalker through its Settings API.
 * 
 * @author Anthony Simons
 * @version 1.0
 */
@SuppressWarnings("serial")
public class TestSettingsPanel extends JPanel 
{
	
	private JComboBox strategyBox;		// test strategy
	private JComboBox modalityBox;		// test modality
	private JSpinner depthSpinner;		// test depth
	private GeneratorDialog dialog;
	
	/**
	 * Creates a TestSettingsPanel for its owning JWalkTester.  This is laid
	 * out as a 3 x 2 grid, each row consisting of a label and another input
	 * widget.  The first row has a combo-box allowing the user to select the
	 * desired test Strategy;  the second row has a combo-box allowing the user
	 * to select the desired test Modality; and the third row has a spinner 
	 * allowing the user to select the desired test path depth (between 0 and
	 * 15).  The default settings are fetched from the Settings API provided
	 * by the JWalkTester.
	 * @param tester the JWalkTester owning this panel.
	 */
	public TestSettingsPanel() {

		setLayout(new GridLayout(4, 2));
		setBorder(BorderFactory.createTitledBorder("Test Settings"));
		Settings settings = Context.getJwalker().getSettings();
		// Create the "Test Strategy" label and combo-box.
		add(new JLabel(" Strategy: "));
		strategyBox = new JComboBox(Strategy.values());
		strategyBox.setSelectedItem(settings.getStrategy());
		strategyBox.setToolTipText("Select the desired test strategy");
		add(strategyBox);
		// Create the "Test Modality" label and combo-box.
		add(new JLabel(" Modality: "));
		modalityBox = new JComboBox(Modality.values());
		modalityBox.setSelectedItem(settings.getModality());
		modalityBox.setToolTipText("Select the desired test modality");
		add(modalityBox);
		// Create the "Test Depth" label and spinner.
		add(new JLabel(" Test Depth: "));
		depthSpinner = new JSpinner(new SpinnerNumberModel(
				settings.getTestDepth(), 0, 20, 1));   // value, min, max, step
		depthSpinner.setToolTipText("Select the maximum length of test sequences");
		add(depthSpinner);
		
		add(new JLabel(" Set Generators "));
		
		JButton genButton = new JButton("Generators");
		genButton.setToolTipText("Add or remove custom test input generators");
		genButton.addActionListener(
				new ActionListener() {
					public void actionPerformed(ActionEvent event) {
						dialog = new GeneratorDialog();
						dialog.setVisible(true);
					}
				}
		);
		
		add(genButton);
	}

	/**
	 * Commits the settings recorded in this panel.  This panel is instructed
	 * by its owning application to upload its local settings to the master
	 * Settings of the JWalker test engine.
	 * @throws SettingsException if any object extracted from the GUI cannot
	 * be converted into a suitable enumerated value or integer value.
	 */
	public void saveSettings() throws SettingsException {
		Settings settings = Context.getJwalker().getSettings();
		Object value = null;
		try {
			value = strategyBox.getSelectedItem();
			settings.setStrategy((Strategy) value);
			value = modalityBox.getSelectedItem();
			settings.setModality((Modality) value);
		} 
		catch (ClassCastException badConversion) {
			SettingsException ex = new SettingsException(value);
			ex.initCause(badConversion);
			throw ex;
		}
		try {
			value = depthSpinner.getValue();
			settings.setTestDepth((Integer) value);
		}
		catch (ClassCastException badConversion) {
			SettingsException ex = new SettingsException(value, true);
			ex.initCause(badConversion);
			throw ex;
		}		
		
		if(dialog != null)
		{
			System.out.println("save");
			dialog.saveSettings(true);
		}
		
	}

}
